﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;


namespace InLAN
{
    public partial class Form_ChatWindow : Form
    {


        #region GlobalVar
        public Socket server_socket = null;
        public Socket client_socket = null;
        public Socket server_GotClient = null;
        public Socket client_GotServer = null;

        public string IpAddress;
        public int PortNum;
        public bool whatjob;
        public string nickname;

        bool CanBeClosed = false;


        Thread reading;
        #endregion GlocalVar


        public Form_ChatWindow(string _IpAddress, int _PortNum,string _nickname, bool _whatjob)
        {
            //if (_whatjob == false)
            //    this.Visible = false;

            this.IpAddress = _IpAddress;
            this.PortNum = _PortNum;
            this.whatjob = _whatjob;
            this.nickname = _nickname;

            InitializeComponent();

            Go();
        }

        public Form_ChatWindow(Socket client)
        {

            client_socket = client;
            InitializeComponent();

            clienting();
        }

        public Form_ChatWindow()
        {
            InitializeComponent();

        }

        #region MyCode



        #region TCPconnection
        public void clienting()
        {
            if (client_socket.Connected)
            {
                reading = new Thread(new ThreadStart(this.get_msg));
                reading.Start();
            }
        }

         public void Go()
        {
            if (whatjob == true)
            {
                IPEndPoint server_ipEndPoint = new IPEndPoint(IPAddress.Any, PortNum);
                server_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                server_socket.Bind(server_ipEndPoint);
                try
                {

                    server_socket.Listen(1);
                    server_GotClient = server_socket.Accept();
                    this.toolStripStatusLabel_Status_ChatWindow.Text = "Status: Connected";
                }
                catch (SocketException e)
                {
                    MessageBox.Show("Unable to listen...");
                    MessageBox.Show(e.ToString());
                }


                reading = new Thread(new ThreadStart(this.get_msg));
                reading.Start();
            }

            if (whatjob == false)
            {
                IPEndPoint client_ipEndPoint = new IPEndPoint(IPAddress.Parse(IpAddress), PortNum);
                client_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                try
                {
                    
                    client_socket.Connect(client_ipEndPoint);
                    this.toolStripStatusLabel_Status_ChatWindow.Text = "Status: Connected";
                    
                }
                catch (SocketException e)
                {
                    MessageBox.Show("Unable to connect to " + nickname + " due to timeout, retrying...");
                    //MessageBox.Show(e.ToString());
                    Go();
                    //return;
                }
                if (client_socket.Connected)
                {
                    reading = new Thread(new ThreadStart(this.get_msg));
                    reading.Start();
                }
            }

        }
        #endregion TCPconnection

        #region MiscFuncs



         public bool status()
         {
             if (server_GotClient != null)
             {
                 return server_GotClient.Connected;
             }
             if (client_socket != null)
             {
                 return client_socket.Connected;
             }

             return false;
         }

         public void closeConnections()
         {
             if (server_GotClient != null)
             {
                 server_GotClient.Shutdown(SocketShutdown.Both);
                 server_GotClient.Close();
             }
             if (client_socket != null)
             {
                 client_socket.Shutdown(SocketShutdown.Both);
                 client_socket.Close();
             }
         }

        public void get_msg()
        {
            byte[] byte_message = new byte[1000];
            string string_message = null;
            int x = 0;
            while (status())
            {
                if (server_GotClient != null)
                {
                    try
                    {
                        x = server_GotClient.Receive(byte_message);
                    }
                    catch
                    {
                        break;
                    }
                }
                if (client_socket != null)
                {
                    //if (this.Visible == false)
                    //{
                    //    this.Invoke(new MethodInvoker(delegate
                    //        {
                    //            this.Visible = true;
                    //        }));
                    //}
                    try
                    {
                        x = client_socket.Receive(byte_message);
                    }
                    catch
                    {
                        break;
                    }
                    finally
                    {
                        
                    }
                }

                if (x != 0)
                {
                    string_message = Encoding.ASCII.GetString(byte_message, 0 , x);
                    DateTime time = DateTime.Now;
                    this.richTextBox_Get.Invoke(new MethodInvoker(delegate
                    {
                        
                        richTextBox_Get.Text = richTextBox_Get.Text + nickname +" ("+ time.ToShortTimeString() +"): " + string_message;

                    }));
                }
                x = 0;
            }
            closeConnections();
            CanBeClosed = true;

            this.Invoke(new MethodInvoker(delegate
            {
                this.toolStripStatusLabel_Status_ChatWindow.Text = "Status: Disconnected";
                this.button_Send.Enabled = false;
                this.richTextBox_Send.Enabled = false;
            }));
        }

        public void send_msg()
        {
            if (richTextBox_Send.Text != "" && richTextBox_Send.Text != "\n")
            {
                string string_message = null;
                byte[] byte_message = new byte[1000];

                if (richTextBox_Send.Text.Length > 1000)
                {
                    MessageBox.Show("Message should be less than 1000 characters...");
                    return;
                }
                string_message = richTextBox_Send.Text;
                if (!string_message.EndsWith("\n"))
                    string_message += "\n";

                richTextBox_Send.Text = string.Empty;
                byte_message = Encoding.ASCII.GetBytes(string_message);
                if (server_GotClient != null)
                    server_GotClient.Send(byte_message, byte_message.Length, SocketFlags.None);
                if (client_socket != null)
                    client_socket.Send(byte_message, byte_message.Length, SocketFlags.None);

                DateTime time = DateTime.Now;
                richTextBox_Get.Text = richTextBox_Get.Text + "Me ("+ time.ToShortTimeString() +"): " + string_message;
                string_message = string.Empty;

            }
        }
        #endregion MiscFuncs

        #endregion MyCode



        private void button_Send_Click(object sender, EventArgs e)
        {
            send_msg();
        }

        private void richTextBox_Send_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 13)
            {
                button_Send_Click( sender,  e);
            }
        }

        private void Form_ChatWindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason == CloseReason.UserClosing)
            {
                if (CanBeClosed == false)
                {
                    e.Cancel = true;
                    this.Visible = false;
                }
                if (CanBeClosed == true)
                {
                    server_socket = null;
                    client_socket = null;
                    server_GotClient = null;
                    client_GotServer = null;
                }
            }
        }

        private void Form_ChatWindow_Load(object sender, EventArgs e)
        {
            this.richTextBox_Get.ReadOnly = true;
            this.richTextBox_Get.BackColor = Color.White;

            this.richTextBox_Send.Focus();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox about = new AboutBox();
            about.Show();
        }

        private void connectionInfoToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Nick Name: " + nickname + "\nPort Num: " + PortNum.ToString() + "\nServer: " + whatjob.ToString() + "\nIP Address of " + nickname + ": " + IpAddress);
        }

        private void richTextBox_Get_TextChanged(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
            {
                this.Activate();
            }
            if (this.Focused == false)
            {
                this.Activate();
            }
            if (this.Visible == false)
            {
                this.Visible = true;
            }
            richTextBox_Get.SelectionStart = richTextBox_Get.Text.Length;
            richTextBox_Get.ScrollToCaret();
        }
    }
}
